package netmodule

import (
	"go_server/common"
	"go_server/components"
	"sync"
	"sync/atomic"

	"github.com/astaxie/beego/logs"
)

type msgQueueMap struct {
	QueueMaps map[int]*msgQueue
	QueueNum  int
	//暂时就这些，其余留着后续的扩展吧
	wg       sync.WaitGroup
	NowIndex atomic.Uint32
}

type msgQueue struct {
	//提供一个chan用于存放任务
	MsgChan chan (*common.MsgQueueItem)
	//提供一把锁解决互斥--chan本身就是线程安全的,所以这把锁没用
	RWMtx sync.RWMutex
	//提供一个chan用于处理协程宕机后close掉，能够异步通知--最终也没有什么意义了
	//MsgQueueAlive chan interface{}
}

var MsgQueueMapInstance *msgQueueMap = nil

// 提供初始化函数
func NewMsgQueue() {
	//拿到指定得到参数
	MsgQueueMapInstance = new(msgQueueMap)
	MsgQueueMapInstance.QueueNum = components.MaxMsgQueueNum
	MsgQueueMapInstance.QueueMaps = make(map[int]*msgQueue)
	MsgQueueMapInstance.NowIndex.Store(0)
	for i := 0; i < MsgQueueMapInstance.QueueNum; i++ {
		q := new(msgQueue)
		q.MsgChan = make(chan *common.MsgQueueItem, components.MaxMsgQueueSize)
		MsgQueueMapInstance.QueueMaps[i] = q

		MsgQueueMapInstance.wg.Add(1)
		go dealMsgQueueItem(q)

	}
	//开启相应的协程
	logs.Debug("[MsgQueue.go:48]成功创建", components.MaxMsgQueueNum, "个用于处理数据的协程", "每个最大缓冲区为：", components.MaxMsgQueueSize)

}

// 提供加任务函数
func AddMsgQueueItemSave(ConSessionItem *common.SessionItem, FullMsg *common.PackageStruct) {
	//创建任务item
	NewMsgQueueItem := new(common.MsgQueueItem)
	NewMsgQueueItem.ConSessionItem = ConSessionItem
	NewMsgQueueItem.TruePackage = FullMsg

	//可以考虑判断并发模式--将消息通过轮询的方式放到不同的协程中处理或者顺序的方式放到同一队列中处理
	if TcpServer.OrderlyDealMsgFlag {
		//hash放入
		MsgQueueMapInstance.QueueMaps[ConSessionItem.ForHashId%MsgQueueMapInstance.QueueNum].MsgChan <- NewMsgQueueItem
	} else {
		//轮询放入---这两部并不是原子操作
		targetIndex := MsgQueueMapInstance.NowIndex.Load()
		MsgQueueMapInstance.NowIndex.Add(1)
		MsgQueueMapInstance.QueueMaps[int(targetIndex%uint32(MsgQueueMapInstance.QueueNum))].MsgChan <- NewMsgQueueItem
	}

}

func dealMsgQueueItem(q *msgQueue) {
	defer MsgQueueMapInstance.wg.Done()

	for {
		select {
		case msg, ok := <-q.MsgChan:
			if !ok {
				logs.Warning("[MsgQueue.go:68]:一个处理消息的msgQueue关闭")
				return
			}
			if msg == nil {
				logs.Error("[MsgQueue.go:72]:获取到的消息居然是nil!!")
				continue
			}
			//然后在这里处理掉
			FindFuncAndCall(msg.ConSessionItem, msg.TruePackage)

		case <-TcpServer.AcceptClose:
			return
		}

	}

}

// // 协程函数去从对应的chan拿数据
// func GetMsgQueueItem() {
//
// 	defer func() {
// 		//close(MsgQueueInstance.MsgQueueAlive)
// 	}() //回收资源并close(MsgQueueAlive)--可能其他协程在等待
//
// 	for {
// 		select {
// 		case NewMsgQueueItem := <-MsgQueueInstance.MsgChan:
// 			if NewMsgQueueItem == nil {
// 				logs.Error("获取的NewMsgQueueItem居然是nil!!")
// 				continue
// 			}
// 			//获取数据，然后handler
// 			err := logic.FindFuncAndCall(NewMsgQueueItem.ConSessionItem, NewMsgQueueItem.TruePackage)
// 			if err != nil {
// 				logs.Warning(err.Error())
// 			}
// 		case <-TcpServer.AcceptClose:
// 			//对接受的值不感兴趣，直接返回即可
// 			return
//
// 		}
// 	}
// }
